feat(dx): Wave 1 session guards — retire repeated push-time traps#583
Conversation
Adds a committed pre-push safety net plus session/operator tooling that encodes this repo's most-repeated traps into machinery: - guard-push.mjs: auto-merge race sentinel (claude/* only; blocks when a PR's auto-merge is armed, ALLOW_AUTOMERGE_PUSH override, fails open when gh absent), format-before-push (closes verify:cheap vs CI gap, SKIP_FORMAT_GUARD override), drift-manifest freshness (SKIP_DRIFT_GUARD override). Includes --self-test. - .githooks/pre-push + install-git-hooks.mjs, auto-installed via a bulletproof postinstall (session-start.sh is remote-gated, so postinstall is the reliable local/CI/remote install point). - check-base-freshness.mjs: advisory stale-base tripwire wired into a second SessionStart hook (never blocks). - docs/operator-backlog.md: consolidates operator/provider-gated actions out of chat memory (statuses seeded from runbooks — confirm before trust). - tests/guard-push.test.ts: 13 tests incl. sha-parity lock vs check-drift. Verified: self-test, 13/13 vitest, eslint, tsc --noEmit, prettier, and a live pre-push smoke against real git all green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 08a83b87d6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (process.env.SKIP_FORMAT_GUARD === "1") { | ||
| return { name: "format", ok: true, skipped: "SKIP_FORMAT_GUARD=1" }; | ||
| } | ||
| const existing = changedFiles.filter((f) => existsSync(f)); |
There was a problem hiding this comment.
Check committed files instead of the worktree
When the worktree is dirty after the commit being pushed, this guard runs Prettier on the filesystem copy of each path rather than the localSha that the pre-push hook parsed from stdin. A committed unformatted change can pass if the developer ran npm run format but forgot to commit the result, and a clean pushed commit can be blocked by later unstaged edits; CI still checks the pushed tree. A small repro is to commit an unformatted file, format it without committing, then push—the guard passes while format:check on the pushed commit would fail.
Useful? React with 👍 / 👎.
| } catch { | ||
| return { name: "drift", ok: true, note: "drift-manifest.json unreadable — drift check skipped" }; | ||
| } | ||
| const verdict = driftVerdict(readFileSync(SCHEMA_PATH, "utf8"), manifest); |
There was a problem hiding this comment.
Compare the pushed schema and manifest
For the same dirty-worktree case, the drift guard compares the current filesystem schema.sql and drift-manifest.json, not the versions in the commit identified by the pre-push localSha. If someone changes supabase/schema.sql, commits it with a stale manifest, then regenerates the manifest but forgets to commit that file, this check reports fresh and allows a push that check:drift will reject in CI. Read both files from the pushed tree or require the relevant paths to be clean before accepting the guard result.
Useful? React with 👍 / 👎.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (8)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds pre-push guards for auto-merge races, formatting, and schema drift; installs the committed hook; introduces advisory base-freshness reporting; wires related npm and session-start commands; and documents operator backlog actions. ChangesPush Safety and Freshness
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Developer
participant SessionStart
participant FreshnessCheck
participant Git
Developer->>SessionStart: start session
SessionStart->>FreshnessCheck: run check-base-freshness.mjs
FreshnessCheck->>Git: fetch and inspect origin/main...HEAD
Git-->>FreshnessCheck: ahead/behind counts
FreshnessCheck-->>Developer: print freshness status
sequenceDiagram
participant PackageInstall
participant GitConfig
participant PrePushHook
participant GuardPush
PackageInstall->>GitConfig: set core.hooksPath to .githooks
PrePushHook->>GuardPush: pass pre-push arguments and stdin
GuardPush-->>PrePushHook: exit with push decision
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
…stinstall - check-docs-links: markdown link targets now resolve relative to the containing file (and accept the repo-root-relative convention), are confined to the repository root, and docs/redesign + docs/superpowers are scanned by default while archive/audit/dated records stay behind --all (review findings from Codex and CodeRabbit) - Dockerfile + Dockerfile.worker: copy scripts/install-git-hooks.mjs into the npm ci stages — main's #583 added it as the npm postinstall hook, so every image build failed at npm ci with the module missing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
#584) * docs: refresh README, add docs index and link checker, fix stale paths - README: correct the verify:cheap chain, document verify:pr-local, and rewrite the CI paragraph to match the risk-scoped ci.yml jobs (changes/static-pr/pr-required aggregate, gated release-browser-matrix) - Add docs/README.md: categorized index of all docs distinguishing maintained docs from point-in-time records and archive - Rewrite docs/agents-guide.md as a non-duplicating pointer to AGENTS.md, codebase-index, and the new docs index - Add scripts/check-docs-links.mjs + `npm run docs:check-links` (advisory; not wired into verify chains) to catch dead repo-path references - Fix stale references it found: phantom favourites-home-page.tsx in the site-map generator (regenerated docs/site-map.md), ambiguous src/lib/supabase paths in codebase-index, archived phase-0 link in search-rag-master-context Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: resolve doc links relative to their file; unbreak image-build postinstall - check-docs-links: markdown link targets now resolve relative to the containing file (and accept the repo-root-relative convention), are confined to the repository root, and docs/redesign + docs/superpowers are scanned by default while archive/audit/dated records stay behind --all (review findings from Codex and CodeRabbit) - Dockerfile + Dockerfile.worker: copy scripts/install-git-hooks.mjs into the npm ci stages — main's #583 added it as the npm postinstall hook, so every image build failed at npm ci with the module missing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
What
First PR of the repo-productivity program. Encodes this repo's most-repeated traps into machinery.
scripts/guard-push.mjs— pre-push safety net, three guards each with an explicit override:claude/*only): blocks a push when the branch's open PR has auto-merge armed, which has orphaned late commits before. OverrideALLOW_AUTOMERGE_PUSH=1; fails open whenghis missing/unauthenticated.prettier --checkon the pushed files, closing theverify:cheap(no format) vs CI (format required) gap. OverrideSKIP_FORMAT_GUARD=1.supabase/schema.sqlchanged without regeneratingdrift-manifest.json. OverrideSKIP_DRIFT_GUARD=1.--self-test..githooks/pre-push+scripts/install-git-hooks.mjs— auto-installed via a bulletproofpostinstall(the SessionStart hook is remote-gated, so postinstall is the reliable local/CI/remote install point).scripts/check-base-freshness.mjs— advisory stale-base tripwire, wired into a secondSessionStarthook. Never blocks.docs/operator-backlog.md— consolidates operator/provider-gated actions out of chat memory. Statuses seeded from runbooks;🔎 verifyrows must be confirmed against live state.tests/guard-push.test.ts— 13 tests incl. a sha-parity lock keepingguard-pushbyte-identical tocheck-drift'snormalizedSchemaSha256.Verification
Local:
--self-test, 13/13 vitest, eslint,tsc --noEmit, prettier, and a live pre-push smoke against real git — all green. No product/runtime code, no migrations; dev-tooling only.🤖 Generated with Claude Code